this.isTransient = false;
this.expanded = false;
this.showWhenLocked = false;
+ this.acknowledged = false;
this._destroyed = false;
this._useActionIcons = false;
this._customContent = false;
this.actor.add_actor(this._iconBin);
this.actor.add_actor(this._counterBin);
- this._source.connect('count-changed', Lang.bind(this, this._updateCount));
+ this._source.connect('count-updated', Lang.bind(this, this._updateCount));
this._updateCount();
},
this.iconName = iconName;
this.iconType = iconType;
- this.count = 0;
-
this.isTransient = false;
this.isChat = false;
this.isMuted = false;
this._setSummaryIcon(this.createIcon(this.ICON_SIZE));
},
- _setCount: function(count, visible) {
- if (isNaN(parseInt(count)))
- throw new Error("Invalid notification count: " + count);
+ get count() {
+ return this.notifications.length;
+ },
- this.count = count;
- this.countVisible = visible;
- this.emit('count-changed');
+ get unseenCount() {
+ return this.notifications.filter(function(n) { return !n.acknowledged; }).length;
},
- _updateCount: function() {
- let count = this.notifications.length;
- this._setCount(count, count > 1);
+ get countVisible() {
+ return this.count > 1;
+ },
+
+ countUpdated: function() {
+ this.emit('count-updated');
},
setTransient: function(isTransient) {
if (this.notifications.length == 0)
this._lastNotificationRemoved();
- this._updateCount();
+ this.countUpdated();
}));
- this._updateCount();
+ this.countUpdated();
},
notify: function(notification) {
+ notification.acknowledged = false;
this.pushNotification(notification);
if (!this.isMuted)
this.emit('notify', notification);
if (!this.notifications[i].resident)
this.notifications[i].destroy();
- this._updateCount();
+ this.countUpdated();
},
// Default implementation is to destroy this source, but subclasses can override
_onNotify: function(source, notification) {
if (this._summaryBoxPointerItem && this._summaryBoxPointerItem.source == source) {
- if (this._summaryBoxPointerState == State.HIDING)
+ if (this._summaryBoxPointerState == State.HIDING) {
// We are in the process of hiding the summary box pointer.
// If there is an update for one of the notifications or
// a new notification to be added to the notification stack
// need to be able to re-parent its actor to a different
// part of the stage.
this._reNotifyAfterHideNotification = notification;
+ } else {
+ // The summary box pointer is showing or shown (otherwise,
+ // this._summaryBoxPointerItem would be null)
+ // Immediately mark the notification as acknowledged, as it's
+ // not going into the queue
+ notification.acknowledged = true;
+ }
+
return;
}
},
_updateShowingNotification: function() {
+ this._notification.acknowledged = true;
+
Tweener.removeTweens(this._notificationBin);
// We auto-expand notifications with CRITICAL urgency.
this._summaryBoxPointerDoneDisplayingId = this._summaryBoxPointerItem.connect('done-displaying-content',
Lang.bind(this, this._escapeTray));
if (this._clickedSummaryItemMouseButton == 1) {
- this._notificationQueue = this._notificationQueue.filter( Lang.bind(this,
- function(notification) {
- return this._summaryBoxPointerItem.source != notification.source;
- }));
+ let newQueue = [];
+ for (let i = 0; i < this._notificationQueue.length; i++) {
+ let notification = this._notificationQueue[i];
+ let sameSource = this._summaryBoxPointerItem.source == notification.source;
+ if (sameSource)
+ notification.acknowledged = true;
+ else
+ newQueue.push(notification);
+ }
+ this._notificationQueue = newQueue;
+
this._summaryBoxPointerItem.prepareNotificationStackForShowing();
this._summaryBoxPointer.bin.child = this._summaryBoxPointerItem.notificationStackView;
this._summaryBoxPointerItem.scrollTo(St.Side.BOTTOM);
return source.hasResidentNotification() && !source.isChat;
},
- _makeNotificationCountText: function(source) {
- if (source.isChat)
- return ngettext("%d new message", "%d new messages", source.count).format(source.count);
+ _makeNotificationCountText: function(count, isChat) {
+ if (isChat)
+ return ngettext("%d new message", "%d new messages", count).format(count);
else
- return ngettext("%d new notification", "%d new notifications", source.count).format(source.count);
+ return ngettext("%d new notification", "%d new notifications", count).format(count);
},
_makeNotificationSource: function(source) {
style_class: 'screen-shield-notification-label' });
textBox.add(label);
- let countLabel = new St.Label({ text: this._makeNotificationCountText(source),
+ let count = source.unseenCount;
+ let countLabel = new St.Label({ text: this._makeNotificationCountText(count, source.isChat),
style_class: 'screen-shield-notification-count-text' });
textBox.add(countLabel);
- box.visible = source.count != 0;
+ box.visible = count != 0;
return [box, countLabel];
},
}
obj.contentUpdatedId = item.connect('content-updated', Lang.bind(this, this._onItemContentUpdated));
- obj.sourceCountChangedId = item.source.connect('count-changed', Lang.bind(this, this._onSourceChanged));
+ obj.sourceCountChangedId = item.source.connect('count-updated', Lang.bind(this, this._onSourceChanged));
obj.sourceTitleChangedId = item.source.connect('title-changed', Lang.bind(this, this._onSourceChanged));
obj.sourceDestroyId = item.source.connect('destroy', Lang.bind(this, this._onSourceDestroy));
this._items.push(obj);
this._residentNotificationBox.add(obj.item.notificationStackView);
} else {
// just update the counter
- obj.countLabel.text = this._makeNotificationCountText(obj.item.source);
- obj.sourceBox.visible = obj.source.count != 0;
+ let count = obj.source.unseenCount;
+ obj.countLabel.text = this._makeNotificationCountText(count, obj.source.isChat);
+ obj.sourceBox.visible = count != 0;
}
this._updateVisibility();